package com.push.xu.xpush.core;

import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;


import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.TextUtils;

import com.push.xu.xpush.listener.ZPushRegisterListener;

public class ZPushContext {
	
	private static ZPushContext zPushContext;
	private static ZPushClient mClient;
	private String mPlatformName;
	private static final String META_DATA_PUSH_HEADER = "ZPush_";

    //all support push platform map
    private LinkedHashMap<String, String> mAllSupportPushPlatformMap = new LinkedHashMap<>();
	
	
    public void init(Application application, ZPushRegisterListener listener) {
        Context context = application.getApplicationContext();
        try {
            //find all support push platform
            Bundle metaData = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA).metaData;
            if (metaData != null) {
                Set<String> allKeys = metaData.keySet();
                if (allKeys != null && !allKeys.isEmpty()) {
                    Iterator<String> iterator = allKeys.iterator();
                    while (iterator.hasNext()) {
                        String key = iterator.next();
                        if (key.startsWith(META_DATA_PUSH_HEADER)) {
                            mAllSupportPushPlatformMap.put(key, metaData.getString(key));
                        }
                    }
                }
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        if (mAllSupportPushPlatformMap.isEmpty()) {
            throw new IllegalArgumentException("check AndroidManifest.xml is have meta-data name is start with ZPush_");
        }

        //choose custom push platform
        Iterator<Map.Entry<String, String>> iterator = mAllSupportPushPlatformMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> next = iterator.next();
            String metaPlatformName = next.getKey();
            String metaPlatformClassName = next.getValue();
            String platformName = metaPlatformName.substring(META_DATA_PUSH_HEADER.length(), metaPlatformName.length());
            try {
                Class<?> currentClz = Class.forName(metaPlatformClassName);
                Class<?>[] interfaces = currentClz.getInterfaces();
                List<Class<?>> allInterfaces = Arrays.asList(interfaces);
                if (allInterfaces.contains(ZPushClient.class)) {
                    //create object with no params
                	ZPushClient iPushClient = (ZPushClient) currentClz.newInstance();
                    if (listener.onRegisterPush(platformName)) {
                        this.mClient = iPushClient;
                        this.mPlatformName = platformName;
                        //invoke IPushClient initContext method
                        iPushClient.initContext(application);
                        break;
                    }
                } else {
                    throw new IllegalArgumentException(metaPlatformClassName + "is not implements " + ZPushClient.class.getName());
                }

            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException("can not find class " + metaPlatformClassName);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        //clear cache client
        mAllSupportPushPlatformMap.clear();
        if (mClient == null) {
            throw new IllegalStateException("onRegisterPush must at least one of them returns to true");
        }
    }
    
	public void register() {
		mClient.register();
	}
	
	public void unregister() {
		mClient.unRegister();
	}
	
	public void clearNotificationById(Context context,int id) {
		mClient.clearNotiById(context, id);
	}

	public String getRegistration(Context context) {
		return mClient.getRegistration(context);
	}

    public void bindAlias(String alias){
        if (TextUtils.isEmpty(alias)) {
            return;
        }
        mClient.bindAlias(alias);
    }

    public void unBindAlias(String alias){
        if (TextUtils.isEmpty(alias)) {
            return;
        }
        mClient.unBindAlias(alias);
    }

    public void addTag(String tag){
        if (TextUtils.isEmpty(tag)) {
            return;
        }
        mClient.addTag(tag);
    }

    public void deleteTag(String tag){
        if (TextUtils.isEmpty(tag)) {
            return;
        }
        mClient.deleteTag(tag);
    }

	public static ZPushContext getInstance() {
		if (zPushContext == null) {
			zPushContext = new ZPushContext();
		}
        return zPushContext;
    }

}
